package service

import (
	"context"
	"fmt"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
)

var (
	Oss = ossService{} // 对象存储服务

	accessKey       = g.Config().GetString("aliyun.oss.accessKey")
	accessKeySecret = g.Config().GetString("aliyun.oss.accessKeySecret")
	endpoint        = g.Config().GetString("aliyun.oss.endpoint")
	bucketName      = g.Config().GetString("aliyun.oss.bucketName")
)

type ossService struct{}

// newClient 获取一个新的链接
func (o *ossService) newClient() (*oss.Client, error) {
	return oss.New(endpoint, accessKey, accessKeySecret)
}

// newBucket 获取一个新的bucket对象
func (o *ossService) newBucket() (*oss.Bucket, error) {
	client, err := o.newClient()
	if err != nil {
		return nil, err
	}
	return client.Bucket(bucketName)
}

// genUrl 通过key生成url, 注意key无需有前缀`/`
func (o *ossService) genUrl(key string) string {
	return fmt.Sprintf("https://%s.%s/%s", bucketName, endpoint, key)
}

func (o *ossService) Upload(ctx context.Context, id uint, ufile *ghttp.UploadFile) (string, error) {
	// 打开文件
	file, err := ufile.Open()
	if err != nil {
		g.Log().Ctx(ctx).Errorf("读取上传的文件失败: %v", err)
		return "", gerror.New("读取文件失败")
	}
	// 新建一个bucket对象
	bucket, err := o.newBucket()
	if err != nil {
		g.Log().Ctx(ctx).Errorf("创建bucket对象失败: %v", err)
		return "", gerror.New("上传文件失败, 请稍后重试")
	}
	// 生成key并上传文件
	key := fmt.Sprintf("%d/%s", id, ufile.Filename)
	err = bucket.PutObject(key, file)
	if err != nil {
		g.Log().Ctx(ctx).Errorf("上传文件失败: %v", err)
		return "", gerror.New("上传文件失败, 请稍后重试")
	}
	return o.genUrl(key), nil
}
